package com.fbs.job.admin.controller;

import com.fbs.job.admin.core.annotation.PermissionLimit;
import com.fbs.job.admin.core.entity.FbsJobActuator;
import com.fbs.job.admin.core.entity.FbsJobInfo;
import com.fbs.job.admin.core.entity.FbsJobLog;
import com.fbs.job.admin.core.entity.FbsJobUser;
import com.fbs.job.admin.core.enums.ExecutorRouteStrategyEnum;
import com.fbs.job.admin.core.enums.MisfireStrategyEnum;
import com.fbs.job.admin.core.enums.ScheduleTypeEnum;
import com.fbs.job.admin.core.enums.TriggerTypeEnum;
import com.fbs.job.admin.core.scheduler.FbsJobScheduler;
import com.fbs.job.admin.core.thread.JobTriggerPoolHelper;
import com.fbs.job.admin.mapper.FbsJobActuatorMapper;
import com.fbs.job.admin.mapper.FbsJobInfoMapper;
import com.fbs.job.admin.mapper.FbsJobLogMapper;
import com.fbs.job.admin.service.JobInfoService;
import com.fbs.job.admin.service.JobUserService;
import com.fbs.job.core.biz.ExecutorBiz;
import com.fbs.job.core.biz.model.LogParam;
import com.fbs.job.core.biz.model.LogResult;
import com.fbs.job.core.enums.ExecutorBlockStrategyEnum;
import com.fbs.job.core.glue.GlueTypeEnum;
import com.fbs.job.core.model.ResultT;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.util.HtmlUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.util.*;

@Controller
@RequestMapping("/log_info")
public class LogInfoController {

    @Resource
    private FbsJobActuatorMapper fbsJobActuatorMapper;


    @Resource
    private FbsJobLogMapper fbsJobLogMapper;
    @Resource
    private FbsJobInfoMapper fbsJobInfoMapper;
    @Resource
    private JobInfoService jobInfoService;


    @RequestMapping
    public String index(HttpServletRequest request,Model model,@RequestParam(required = false, defaultValue = "-1") int jobId) {

        // 执行器列表
        List<FbsJobActuator> jobActuatorsList_all =  fbsJobActuatorMapper.findAll();

        // filter group
        List<FbsJobActuator> jobActuatorList = JobInfoController.filterJobActuatorByRole(request, jobActuatorsList_all);
        if (jobActuatorList==null || jobActuatorList.size()==0) {
            throw new RuntimeException("jobgroup_empty");
        }

        model.addAttribute("JobActuatorList", jobActuatorList);

        // 任务
        if (jobId > 0) {
            FbsJobInfo jobInfo = fbsJobInfoMapper.getById(jobId);
            if (jobInfo == null) {
                throw new RuntimeException("任务ID非法");
            }

            model.addAttribute("jobInfo", jobInfo);

            // valid permission
            JobInfoController.validPermission(request, jobInfo.getJobActuator());
        }
        return "log/loginfo";
    }

    @RequestMapping("/add")
    @ResponseBody
    public ResultT<String> add(@RequestBody FbsJobInfo jobInfo) {
        return jobInfoService.add(jobInfo);
    }


    @RequestMapping("/logDetailCat")
    @ResponseBody
    public ResultT<LogResult> logDetailCat(long logId, int fromLineNum){
        try {
            // valid
            FbsJobLog jobLog = fbsJobLogMapper.getById(logId);
            if (jobLog == null) {
                return new ResultT<LogResult>(ResultT.FAIL_CODE, "日志ID非法");
            }

            // log cat
            ExecutorBiz executorBiz = FbsJobScheduler.getExecutorBiz(jobLog.getExecutorAddress());
            ResultT<LogResult> logResult = executorBiz.log(new LogParam(jobLog.getTriggerTime().getTime(), logId, fromLineNum));

            // is end
            if (logResult.getData()!=null && logResult.getData().getFromLineNum() > logResult.getData().getToLineNum()) {
                if (jobLog.getHandleCode() > 0) {
                    logResult.getData().setEnd(true);
                }
            }

            // fix xss
            if (logResult.getData()!=null && StringUtils.hasText(logResult.getData().getLogContent())) {
                String newLogContent = logResult.getData().getLogContent();
                newLogContent = HtmlUtils.htmlEscape(newLogContent, "UTF-8");
                logResult.getData().setLogContent(newLogContent);
            }

            return logResult;
        } catch (Exception e) {
            return new ResultT<LogResult>(ResultT.FAIL_CODE, e.getMessage());
        }
    }

    public static class TriggerJobReq{
        int id;
        String executorParam;
        String addressList;

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getExecutorParam() {
            return executorParam;
        }

        public void setExecutorParam(String executorParam) {
            this.executorParam = executorParam;
        }

        public String getAddressList() {
            return addressList;
        }

        public void setAddressList(String addressList) {
            this.addressList = addressList;
        }
    }


    @RequestMapping("/trigger")
    @ResponseBody
    //@PermissionLimit(limit = false)
    public ResultT<String> triggerJob(@RequestBody TriggerJobReq req) {
        // force cover job param
        if (req.getExecutorParam() == null) {
            req.setExecutorParam("");
        }

        JobTriggerPoolHelper.trigger(req.getId(), TriggerTypeEnum.MANUAL, -1, null, req.getExecutorParam(), req.getAddressList());
        return ResultT.success();
    }




    @RequestMapping("/pageList")
    @ResponseBody
    public Map<String, Object> pageList(HttpServletRequest request,
                                        @RequestParam(required = false, defaultValue = "0") int page,
                                        @RequestParam(required = false, defaultValue = "10") int rows,
                                        int jobActuator, int jobId, int logStatus, String triggerTime) {

        // valid permission
        JobInfoController.validPermission(request,jobActuator);	// 仅管理员支持查询全部；普通用户仅支持查询有权限的 jobGroup
        // parse param
        Date triggerTimeStart = null;
        Date triggerTimeEnd = null;
        if (triggerTime!=null && triggerTime.trim().length()>0) {
            String[] temp = triggerTime.split(" - ");
            if (temp.length == 2) {
                try {
                    triggerTimeStart = DateUtils.parseDate(temp[0],"yyyy-MM-dd HH:mm:ss");
                } catch (ParseException e) {
                    triggerTimeStart =new Date(Long.parseLong(temp[0]));
                }
                try {
                    triggerTimeEnd = DateUtils.parseDate(temp[1],"yyyy-MM-dd HH:mm:ss");
                } catch (ParseException e) {
                    triggerTimeEnd= new Date(Long.parseLong(temp[1]));
                }
            }
        }

        // page query
        List<FbsJobLog> list = fbsJobLogMapper.pageList(page-1, rows, jobActuator, jobId, triggerTimeStart, triggerTimeEnd, logStatus);
        int list_count = fbsJobLogMapper.pageListCount(page-1, rows, jobActuator, jobId, triggerTimeStart, triggerTimeEnd, logStatus);
        // package result
        Map<String, Object> maps = new HashMap<String, Object>();
        maps.put("recordsTotal", list_count);		// 总记录数
        maps.put("recordsFiltered", list_count);	// 过滤后的总记录数
        maps.put("data", list);  					// 分页列表
        maps.put("code",0);					// 分页列表
        return maps;
    }











































    public static List<FbsJobActuator> filterJobActuatorByRole(HttpServletRequest request, List<FbsJobActuator> jobActuatorList_all){
        List<FbsJobActuator> jobActuatorList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(jobActuatorList_all)) {
            FbsJobUser loginUser = (FbsJobUser) request.getAttribute(JobUserService.LOGIN_IDENTITY_KEY);
            if (loginUser.getRole() == 1) {
                jobActuatorList = jobActuatorList_all;
            } else {
                List<String> groupIdsList = new ArrayList<>();
                if (loginUser.getPermission()!=null && loginUser.getPermission().trim().length()>0) {
                    groupIdsList = Arrays.asList(loginUser.getPermission().trim().split(","));
                }
                for (FbsJobActuator actuator:jobActuatorList_all) {
                    if (groupIdsList.contains(String.valueOf(actuator.getId()))) {
                        jobActuatorList.add(actuator);
                    }
                }
            }
        }
        return jobActuatorList;
    }

}
